/*
 *  RESTful DDS is a prototyping effort to demonstrate how DDS could be combined
 *  with HTTP clients, extending the realm of pub/sub distribution to true wide
 *  area networking.
 *
 *  Copyright (C) 2009 PrismTech Ltd.
 *  reinier.torenbeek@gmail.com
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License Version 3 dated 29 June 2007, as published by the
 *  Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with restful-dds; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package Display;

/**
 * The principle class for the application "DisplayApp".
 * 
 * This class can be used to start and stop all DDS entities contained
 * by "DisplayApp".
 */
public final class DisplayAppWrapper {

	private DisplayAppWrapper() {
	}

	@SuppressWarnings("serial")
	public static class WrapperException extends Exception {
		private final String m_reason;
		private final DDS.Entity m_entity;
		private final String m_sourceType;
		private final String m_method;
		private final int m_returnValue;
		private final String m_wrapper;

		protected WrapperException() {
			m_reason = null;
			m_entity = null;
			m_sourceType = null;
			m_method = null;
			m_returnValue = DDS.RETCODE_OK.value;
			m_wrapper = null;
		}

		public WrapperException(final String reason, final DDS.Entity entity,
				final String sourceType, final String method,
				final int returnValue, final String wrapper) {
			m_reason = reason;
			m_entity = entity;
			m_sourceType = sourceType;
			m_method = method;
			m_returnValue = returnValue;
			m_wrapper = wrapper;
		}

		public String getSourceType() {
			return m_sourceType;
		}

		public String getReason() {
			return m_reason;
		}

		public DDS.Entity getEntity() {
			return m_entity;
		}

		public String getMethod() {
			return m_method;
		}

		public int getReturnValue() {
			return m_returnValue;
		}

		public String getWrapper() {
			return m_wrapper;
		}

		@Override
		public String getMessage() {
			final StringBuilder message = new StringBuilder();

			message.append(String.format("[%s] call %s.%s failed.", m_wrapper,
					m_sourceType, m_method));

			if (m_returnValue != DDS.RETCODE_OK.value) {
				message.append(" ReturnValue: ");
				message.append(m_returnValue);
			}

			if (m_reason != null) {
				message.append(" Reason: ");
				message.append(m_reason);
			}

			return message.toString();
		}

	}

	@SuppressWarnings("serial")
	public static class ContainerWrapperException extends WrapperException {
		private final static String LINE_SEPARATOR = System
				.getProperty("line.separator"); //$NON-NLS-1$
		private final java.util.List<WrapperException> m_exceptions;

		public ContainerWrapperException(
				final java.util.List<WrapperException> exceptions) {
			m_exceptions = exceptions;
		}

		public java.util.List<WrapperException> getExceptions() {
			return java.util.Collections.unmodifiableList(m_exceptions);
		}

		@Override
		public String getMessage() {
			final StringBuilder message = new StringBuilder();

			for (WrapperException exception : m_exceptions) {
				message.append(exception.getMessage());
				message.append(LINE_SEPARATOR);
			}

			return message.toString();
		}
	}

	/**
	 * Start all DDS Entity wrappers for "DisplayApp". 
	 * All DDS Entities contained by "DisplayApp" will be created and initialized.
	 * WaitSet and Condition wrappers are NOT started.
	 * 
	 * @throws WrapperException
	 */
	public synchronized static void start() throws WrapperException {
		BattlefieldParticipantWrapper.start();
		ParticipantWrapper.start();
	}

	/**
	 * Stop all DDS Entity wrappers for "DisplayApp".
	 * All DDS Entities contained by "DisplayApp" will be deleted.
	 * WaitSet and Condition wrappers are stopped.
	 *
	 * @throws WrapperException
	 */
	public synchronized static void stop() throws WrapperException {

		BattlefieldParticipantWrapper.stop();
		ParticipantWrapper.stop();

	}

	/**
	 * Base class for the implementation of the listener "ObjectLocationDataReaderListener"
	 * 
	 * This class must be extended, and any abstract methods must be implemented.
	 * Instances of the sub-class can then be added to the appropriate entities as
	 * defined in the application model.
	 */
	public static abstract class ObjectLocationDataReaderListener implements
			DDS.DataReaderListener {
		public final int STATUS_MASK = DDS.DATA_AVAILABLE_STATUS.value;

		public abstract void on_data_available(DDS.DataReader dataReader);

		public final void on_sample_lost(DDS.DataReader dataReader,
				DDS.SampleLostStatus status) {
		}

		public final void on_requested_deadline_missed(
				DDS.DataReader dataReader,
				DDS.RequestedDeadlineMissedStatus status) {
		}

		public final void on_sample_rejected(DDS.DataReader dataReader,
				DDS.SampleRejectedStatus status) {
		}

		public final void on_liveliness_changed(DDS.DataReader dataReader,
				DDS.LivelinessChangedStatus status) {
		}

		public final void on_subscription_matched(DDS.DataReader dataReader,
				DDS.SubscriptionMatchedStatus status) {
		}

		public final void on_requested_incompatible_qos(
				DDS.DataReader dataReader,
				DDS.RequestedIncompatibleQosStatus status) {
		}

	}

	/**
	 * Base class for the implementation of the listener "PointTrackDataReaderListener"
	 * 
	 * This class must be extended, and any abstract methods must be implemented.
	 * Instances of the sub-class can then be added to the appropriate entities as
	 * defined in the application model.
	 */
	public static abstract class PointTrackDataReaderListener implements
			DDS.DataReaderListener {
		public final int STATUS_MASK = DDS.DATA_AVAILABLE_STATUS.value;

		public abstract void on_data_available(DDS.DataReader dataReader);

		public final void on_sample_lost(DDS.DataReader dataReader,
				DDS.SampleLostStatus status) {
		}

		public final void on_requested_deadline_missed(
				DDS.DataReader dataReader,
				DDS.RequestedDeadlineMissedStatus status) {
		}

		public final void on_sample_rejected(DDS.DataReader dataReader,
				DDS.SampleRejectedStatus status) {
		}

		public final void on_liveliness_changed(DDS.DataReader dataReader,
				DDS.LivelinessChangedStatus status) {
		}

		public final void on_subscription_matched(DDS.DataReader dataReader,
				DDS.SubscriptionMatchedStatus status) {
		}

		public final void on_requested_incompatible_qos(
				DDS.DataReader dataReader,
				DDS.RequestedIncompatibleQosStatus status) {
		}

	}

	/**
	 * Base class for the implementation of the listener "TrackStateDataReaderListener"
	 * 
	 * This class must be extended, and any abstract methods must be implemented.
	 * Instances of the sub-class can then be added to the appropriate entities as
	 * defined in the application model.
	 */
	public static abstract class TrackStateDataReaderListener implements
			DDS.DataReaderListener {
		public final int STATUS_MASK = DDS.DATA_AVAILABLE_STATUS.value;

		public abstract void on_data_available(DDS.DataReader dataReader);

		public final void on_sample_lost(DDS.DataReader dataReader,
				DDS.SampleLostStatus status) {
		}

		public final void on_requested_deadline_missed(
				DDS.DataReader dataReader,
				DDS.RequestedDeadlineMissedStatus status) {
		}

		public final void on_sample_rejected(DDS.DataReader dataReader,
				DDS.SampleRejectedStatus status) {
		}

		public final void on_liveliness_changed(DDS.DataReader dataReader,
				DDS.LivelinessChangedStatus status) {
		}

		public final void on_subscription_matched(DDS.DataReader dataReader,
				DDS.SubscriptionMatchedStatus status) {
		}

		public final void on_requested_incompatible_qos(
				DDS.DataReader dataReader,
				DDS.RequestedIncompatibleQosStatus status) {
		}

	}

	public final static class BattlefieldParticipantWrapper {
		private static DDS.DomainParticipantFactory dpf = DDS.DomainParticipantFactory
				.get_instance();
		private static DDS.DomainParticipant m_participant = null;
		private static String m_Domain = null;

		private static DDS.DomainParticipantListener m_domainParticipantListener = null;
		private static int m_statusMask = -1;

		private BattlefieldParticipantWrapper() {
		}

		/**
		 * Start all Entity wrappers for "BattlefieldParticipant".
		 * All DDS Entities contained by "BattlefieldParticipant" and all associated Topics will be created and initialized.
		 *
		 * @throws WrapperException
		 */
		synchronized static void start() throws WrapperException {
			if (m_participant != null) {
				return;
			}

			DDS.DomainParticipantQosHolder participantQoSHolder = new DDS.DomainParticipantQosHolder();
			getDomainParticipant_QoS(participantQoSHolder);

			if (m_domainParticipantListener == null) {
				m_participant = dpf.create_participant(m_Domain,
						participantQoSHolder.value,
						m_domainParticipantListener, DDS.ANY_STATUS.value);
			} else {
				m_participant = dpf.create_participant(m_Domain,
						participantQoSHolder.value,
						m_domainParticipantListener, m_statusMask);
			}

			if (m_participant == null) {
				throw new WrapperException("Null returned", null,
						"DDS.DomainParticipantFactory", "create_participant",
						DDS.RETCODE_OK.value,
						"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.start()");
			}

			participantQoSHolder = null;

			setDefaultPublisherQoS();
			setDefaultSubscriberQoS();

			SubscriberWrapper.start();
		}

		/**
		 * Stop all Entitiy wrappers for "BattlefieldParticipant".
		 *
		 * @throws WrapperException
		 */
		synchronized static void stop() throws WrapperException {
			if (m_participant == null) {
				return;
			}

			int retcode = DDS.RETCODE_OK.value;
			final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();

			try {
				SubscriberWrapper.stop();
			} catch (WrapperException e) {
				exceptions.add(e);
			}

			try {
				track.ObjectLocation_topicWrapper.stop(m_participant);
			} catch (track.ObjectLocation_topicWrapper.WrapperException e) {
				exceptions.add(new WrapperException(e.getReason(), e
						.getEntity(), e.getSourceType(), e.getMethod(), e
						.getReturnValue(), e.getWrapper()));
				exceptions
						.add(new WrapperException(null, null,
								"ObjectLocation_topicWrapper", "stop", 0,
								"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.stop()"));
			}

			// N.B. this will delete all entities created
			//      by this DomainParticipant
			retcode = m_participant.delete_contained_entities();

			if (retcode != DDS.RETCODE_OK.value) {
				exceptions
						.add(new WrapperException(null, m_participant,
								"DDS.DomainParticipant",
								"delete_contained_entities", retcode,
								"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.stop()"));
			}

			retcode = dpf.delete_participant(m_participant);

			if (retcode != DDS.RETCODE_OK.value) {
				exceptions
						.add(new WrapperException(null, null,
								"DDS.DomainParticipantFactory",
								"delete_participant", retcode,
								"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.stop()"));
			}

			m_participant = null;

			if (!exceptions.isEmpty()) {
				throw new ContainerWrapperException(exceptions);
			}
		}

		/**
		 * Get the QoS values for "BattlefieldParticipant"
		 *
		 */
		static void getDomainParticipant_QoS(DDS.DomainParticipantQosHolder qos) {
			dpf.get_default_participant_qos(qos);

			qos.value.entity_factory.autoenable_created_entities = true;
		}

		/**
		 * Set the default QoS for Publishers
		 */
		private static void setDefaultPublisherQoS() {
			DDS.PublisherQosHolder qos = new DDS.PublisherQosHolder();
			m_participant.get_default_publisher_qos(qos);

			qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
			qos.value.presentation.coherent_access = false;
			qos.value.presentation.ordered_access = false;

			qos.value.partition.name = new String[0];

			qos.value.entity_factory.autoenable_created_entities = true;

			m_participant.set_default_publisher_qos(qos.value);
		}

		/**
		 * Set the default QoS for Subscribers
		 */
		private static void setDefaultSubscriberQoS() {
			DDS.SubscriberQosHolder qos = new DDS.SubscriberQosHolder();
			m_participant.get_default_subscriber_qos(qos);

			qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
			qos.value.presentation.coherent_access = false;
			qos.value.presentation.ordered_access = false;

			qos.value.partition.name = new String[0];

			qos.value.entity_factory.autoenable_created_entities = true;

			m_participant.set_default_subscriber_qos(qos.value);
		}

		/**
		 * Get the DDS Entity for "BattlefieldParticipant"
		 *
		 * @return The DomainParticipant "BattlefieldParticipant"
		 */
		public synchronized static DDS.DomainParticipant getDomainParticipant() {
			return m_participant;
		}

		public final static class SubscriberWrapper {
			private static DDS.Subscriber m_subscriber = null;
			private static DDS.SubscriberListener m_subscriberListener = null;
			private static int m_statusMask = -1;

			private SubscriberWrapper() {
			}

			/**
			 * Create the DDS.Subscriber and start all child DataReaders.
			 * @throws WrapperException
			 */
			synchronized static void start() throws WrapperException {
				if (m_subscriber != null) {
					return;
				}

				DDS.SubscriberQosHolder subscriberQoSHolder = new DDS.SubscriberQosHolder();
				getSubscriberQoS(subscriberQoSHolder);

				if (m_subscriberListener == null) {
					m_subscriber = m_participant.create_subscriber(
							subscriberQoSHolder.value, m_subscriberListener,
							DDS.ANY_STATUS.value);
				} else {
					m_subscriber = m_participant.create_subscriber(
							subscriberQoSHolder.value, m_subscriberListener,
							m_statusMask);
				}

				subscriberQoSHolder = null;

				if (m_subscriber == null) {
					throw new WrapperException(
							null,
							m_participant,
							"DDS.DomainParticipant",
							"create_subscriber",
							DDS.RETCODE_OK.value,
							"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.start()");
				}

				track.BattlefieldWrapper.addSubscriber(m_subscriber);

				setDefaultDataReaderQoS();

				try {
					ObjectLocationDataReaderWrapper.start();
				} catch (WrapperException eStart) {
					try {
						stop();
					} catch (WrapperException eStop) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();
						exceptions.add(eStart);
						exceptions.add(eStop);
						throw new ContainerWrapperException(exceptions);
					}

					throw eStart;
				}

			}

			/**
			 * Stop all child DataReaders and delete the DDS.Subscriber.
			 * @throws WrapperException
			 */
			synchronized static void stop() throws WrapperException {
				if (m_subscriber == null) {
					return;
				}

				final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();
				track.BattlefieldWrapper.removeSubscriber(m_subscriber);

				try {
					ObjectLocationDataReaderWrapper.stop();
				} catch (WrapperException e) {
					exceptions.add(e);
				}

				int retcode = m_participant.delete_subscriber(m_subscriber);
				m_subscriber = null;

				if (retcode != DDS.RETCODE_OK.value) {
					exceptions
							.add(new WrapperException(
									null,
									m_participant,
									"DDS.DomainParticipant",
									"delete_subscriber",
									retcode,
									"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.stop()"));
				}

				if (!exceptions.isEmpty()) {
					throw new ContainerWrapperException(exceptions);
				}
			}

			static void getSubscriberQoS(DDS.SubscriberQosHolder qos) {
				m_participant.get_default_subscriber_qos(qos);

				qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
				qos.value.presentation.coherent_access = false;
				qos.value.presentation.ordered_access = false;
				qos.value.entity_factory.autoenable_created_entities = true;

				qos.value.partition.name = new String[1];

				qos.value.partition.name[0] = track.BattlefieldWrapper
						.getName();

				m_participant.set_default_subscriber_qos(qos.value);
			}

			private static void setDefaultDataReaderQoS() {
				DDS.DataReaderQosHolder qos = new DDS.DataReaderQosHolder();
				m_subscriber.get_default_datareader_qos(qos);

				qos.value.durability.kind = DDS.DurabilityQosPolicyKind.VOLATILE_DURABILITY_QOS;
				qos.value.deadline.period = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);
				qos.value.ownership.kind = DDS.OwnershipQosPolicyKind.SHARED_OWNERSHIP_QOS;

				qos.value.latency_budget.duration = new DDS.Duration_t(0, 0);
				qos.value.liveliness.kind = DDS.LivelinessQosPolicyKind.AUTOMATIC_LIVELINESS_QOS;
				qos.value.liveliness.lease_duration = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);

				// Not implemented in OpenSplice 3.2.2 and before
				qos.value.time_based_filter.minimum_separation = new DDS.Duration_t(
						0, 0);

				qos.value.reliability.kind = DDS.ReliabilityQosPolicyKind.BEST_EFFORT_RELIABILITY_QOS;
				qos.value.reliability.max_blocking_time = new DDS.Duration_t(0,
						100000000);
				qos.value.destination_order.kind = DDS.DestinationOrderQosPolicyKind.BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
				qos.value.history.kind = DDS.HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
				qos.value.history.depth = 1;
				qos.value.resource_limits.max_instances = -1;
				qos.value.resource_limits.max_samples = -1;
				qos.value.resource_limits.max_samples_per_instance = -1;
				qos.value.reader_data_lifecycle.autopurge_disposed_samples_delay = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);
				qos.value.reader_data_lifecycle.autopurge_nowriter_samples_delay = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);

				m_subscriber.set_default_datareader_qos(qos.value);
			}

			public synchronized static DDS.Subscriber getSubscriber() {
				return m_subscriber;
			}

			public final static class ObjectLocationDataReaderWrapper {
				private static track.ObjectLocationDataReader m_reader = null;
				private static DDS.DataReaderListener m_readerListener = null;
				private static int m_statusMask = -1;

				private ObjectLocationDataReaderWrapper() {
				}

				/**
				 * Create the "ObjectLocationDataReader".
				 * @throws WrapperException
				 */
				static synchronized void start() throws WrapperException {
					if (m_reader != null) {
						return;
					}

					DDS.TopicDescription topic = null;

					try {
						topic = track.ObjectLocation_topicWrapper
								.start(m_participant);
					} catch (track.ObjectLocation_topicWrapper.WrapperException e) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();

						exceptions.add(new WrapperException(e.getReason(), e
								.getEntity(), e.getSourceType(), e.getMethod(),
								e.getReturnValue(), e.getWrapper()));
						exceptions
								.add(new WrapperException(
										null,
										null,
										"ObjectLocation_topicWrapper",
										"start",
										DDS.RETCODE_OK.value,
										"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.ObjectLocationDataReaderWrapper.start()"));

						throw new ContainerWrapperException(exceptions);
					}

					DDS.DataReaderQosHolder dwQoS = new DDS.DataReaderQosHolder();
					getDataReaderQoS(dwQoS);

					/* Create datareader */

					DDS.DataReader dataReader = null;

					if (m_readerListener == null) {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener,
								DDS.ANY_STATUS.value);
					} else {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener, m_statusMask);
					}

					if (dataReader == null) {
						throw new WrapperException("Null returned",
								m_subscriber, "DDS.Subscriber", "create", 0,
								"ObjectLocationDataReaderWrapper.start()");
					}

					m_reader = track.ObjectLocationDataReaderHelper
							.narrow(dataReader);

					if (m_reader == null) {
						throw new WrapperException("Null returned", null,
								"track.ObjectLocationDataReaderHelper",
								"narrow", 0,
								"ObjectLocationDataReaderWrapper.start()");
					}

				}

				/**
				 * Delete the "ObjectLocationDataReader".
				 * @throws WrapperException
				 */
				static synchronized void stop() throws WrapperException {
					if (m_reader == null) {
						return;
					}

					int retcode = m_subscriber.delete_datareader(m_reader);
					m_reader = null;

					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(null, m_subscriber,
								"DDS.Subscriber", "delete_datareader", retcode,
								"ObjectLocationDataReaderWrapper.stop()");
					}
				}

				/**
				 *
				 */
				static void getDataReaderQoS(DDS.DataReaderQosHolder qos) {
					m_subscriber.get_default_datareader_qos(qos);

					// Not implemented in OpenSplice 3.2.2 and before
					qos.value.time_based_filter.minimum_separation = new DDS.Duration_t(
							0, 0);

					qos.value.reader_data_lifecycle.autopurge_disposed_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.reader_data_lifecycle.autopurge_nowriter_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.durability.kind = DDS.DurabilityQosPolicyKind.VOLATILE_DURABILITY_QOS;
					qos.value.deadline.period = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);

					qos.value.latency_budget.duration = new DDS.Duration_t(0, 0);
					qos.value.ownership.kind = DDS.OwnershipQosPolicyKind.SHARED_OWNERSHIP_QOS;
					qos.value.liveliness.kind = DDS.LivelinessQosPolicyKind.AUTOMATIC_LIVELINESS_QOS;
					qos.value.liveliness.lease_duration = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.reliability.kind = DDS.ReliabilityQosPolicyKind.BEST_EFFORT_RELIABILITY_QOS;
					qos.value.reliability.max_blocking_time = new DDS.Duration_t(
							0, 100000000);
					qos.value.destination_order.kind = DDS.DestinationOrderQosPolicyKind.BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
					qos.value.history.kind = DDS.HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
					qos.value.history.depth = 1;
					qos.value.resource_limits.max_instances = -1;
					qos.value.resource_limits.max_samples = -1;
					qos.value.resource_limits.max_samples_per_instance = -1;
				}

				/**
				 *
				 */
				public synchronized static track.ObjectLocationDataReader getDataReader() {
					return m_reader;
				}

				/**
				 * Attach a listener of type "ObjectLocationDataReaderListener" to this DataReader.
				 *
				 * @param listener The listener to attach
				 * @return A DDS return code for the "attach" operation
				 */
				public synchronized static void attach(
						ObjectLocationDataReaderListener listener)
						throws WrapperException {
					m_readerListener = listener;
					m_statusMask = listener.STATUS_MASK;
					DDS.DataReader reader = m_reader;

					if (reader == null) {
						return;
					}

					final int retcode = reader.set_listener(listener,
							listener.STATUS_MASK);
					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(
								null,
								reader,
								"DDS.DataReader",
								"set_listener",
								retcode,
								"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.ObjectLocationDataReaderWrapper.attach()");
					}
				}

				/**
				 * Detach the listener from this DataReader.
				 *
				 * @param listener The listener to detach
				 * @return A DDS return code for the "detach" operation
				 */
				public synchronized static void detach(
						ObjectLocationDataReaderListener listener)
						throws WrapperException {
					if (listener != m_readerListener) {
						throw new WrapperException(
								"Listener is not attached",
								null,
								"ObjectLocationDataReaderWrapper",
								"detach",
								DDS.RETCODE_OK.value,
								"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.ObjectLocationDataReaderWrapper.detach()");
					}

					m_readerListener = null;

					if (m_reader != null) {
						final int retcode = m_reader.set_listener(null, 0);
						if (retcode != DDS.RETCODE_OK.value) {
							throw new WrapperException(
									null,
									m_reader,
									"DDS.DataReader",
									"set_listener",
									retcode,
									"Display.DisplayAppWrapper.BattlefieldParticipantWrapper.SubscriberWrapper.ObjectLocationDataReaderWrapper.detach()");
						}
					}

				}

			}

		}

	}

	public final static class ParticipantWrapper {
		private static DDS.DomainParticipantFactory dpf = DDS.DomainParticipantFactory
				.get_instance();
		private static DDS.DomainParticipant m_participant = null;
		private static String m_Domain = null;

		private static DDS.DomainParticipantListener m_domainParticipantListener = null;
		private static int m_statusMask = -1;

		private ParticipantWrapper() {
		}

		/**
		 * Start all Entity wrappers for "Participant".
		 * All DDS Entities contained by "Participant" and all associated Topics will be created and initialized.
		 *
		 * @throws WrapperException
		 */
		synchronized static void start() throws WrapperException {
			if (m_participant != null) {
				return;
			}

			DDS.DomainParticipantQosHolder participantQoSHolder = new DDS.DomainParticipantQosHolder();
			getDomainParticipant_QoS(participantQoSHolder);

			if (m_domainParticipantListener == null) {
				m_participant = dpf.create_participant(m_Domain,
						participantQoSHolder.value,
						m_domainParticipantListener, DDS.ANY_STATUS.value);
			} else {
				m_participant = dpf.create_participant(m_Domain,
						participantQoSHolder.value,
						m_domainParticipantListener, m_statusMask);
			}

			if (m_participant == null) {
				throw new WrapperException("Null returned", null,
						"DDS.DomainParticipantFactory", "create_participant",
						DDS.RETCODE_OK.value,
						"Display.DisplayAppWrapper.ParticipantWrapper.start()");
			}

			participantQoSHolder = null;

			setDefaultPublisherQoS();
			setDefaultSubscriberQoS();

			SubscriberWrapper.start();
		}

		/**
		 * Stop all Entitiy wrappers for "Participant".
		 *
		 * @throws WrapperException
		 */
		synchronized static void stop() throws WrapperException {
			if (m_participant == null) {
				return;
			}

			int retcode = DDS.RETCODE_OK.value;
			final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();

			try {
				SubscriberWrapper.stop();
			} catch (WrapperException e) {
				exceptions.add(e);
			}

			try {
				track.PointTrack_topicWrapper.stop(m_participant);
			} catch (track.PointTrack_topicWrapper.WrapperException e) {
				exceptions.add(new WrapperException(e.getReason(), e
						.getEntity(), e.getSourceType(), e.getMethod(), e
						.getReturnValue(), e.getWrapper()));
				exceptions.add(new WrapperException(null, null,
						"PointTrack_topicWrapper", "stop", 0,
						"Display.DisplayAppWrapper.ParticipantWrapper.stop()"));
			}
			try {
				track.TrackState_topicWrapper.stop(m_participant);
			} catch (track.TrackState_topicWrapper.WrapperException e) {
				exceptions.add(new WrapperException(e.getReason(), e
						.getEntity(), e.getSourceType(), e.getMethod(), e
						.getReturnValue(), e.getWrapper()));
				exceptions.add(new WrapperException(null, null,
						"TrackState_topicWrapper", "stop", 0,
						"Display.DisplayAppWrapper.ParticipantWrapper.stop()"));
			}

			// N.B. this will delete all entities created
			//      by this DomainParticipant
			retcode = m_participant.delete_contained_entities();

			if (retcode != DDS.RETCODE_OK.value) {
				exceptions.add(new WrapperException(null, m_participant,
						"DDS.DomainParticipant", "delete_contained_entities",
						retcode,
						"Display.DisplayAppWrapper.ParticipantWrapper.stop()"));
			}

			retcode = dpf.delete_participant(m_participant);

			if (retcode != DDS.RETCODE_OK.value) {
				exceptions.add(new WrapperException(null, null,
						"DDS.DomainParticipantFactory", "delete_participant",
						retcode,
						"Display.DisplayAppWrapper.ParticipantWrapper.stop()"));
			}

			m_participant = null;

			if (!exceptions.isEmpty()) {
				throw new ContainerWrapperException(exceptions);
			}
		}

		/**
		 * Get the QoS values for "Participant"
		 *
		 */
		static void getDomainParticipant_QoS(DDS.DomainParticipantQosHolder qos) {
			dpf.get_default_participant_qos(qos);

			qos.value.entity_factory.autoenable_created_entities = true;
		}

		/**
		 * Set the default QoS for Publishers
		 */
		private static void setDefaultPublisherQoS() {
			DDS.PublisherQosHolder qos = new DDS.PublisherQosHolder();
			m_participant.get_default_publisher_qos(qos);

			qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
			qos.value.presentation.coherent_access = false;
			qos.value.presentation.ordered_access = false;

			qos.value.partition.name = new String[0];

			qos.value.entity_factory.autoenable_created_entities = true;

			m_participant.set_default_publisher_qos(qos.value);
		}

		/**
		 * Set the default QoS for Subscribers
		 */
		private static void setDefaultSubscriberQoS() {
			DDS.SubscriberQosHolder qos = new DDS.SubscriberQosHolder();
			m_participant.get_default_subscriber_qos(qos);

			qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
			qos.value.presentation.coherent_access = false;
			qos.value.presentation.ordered_access = false;

			qos.value.partition.name = new String[0];

			qos.value.entity_factory.autoenable_created_entities = true;

			m_participant.set_default_subscriber_qos(qos.value);
		}

		/**
		 * Get the DDS Entity for "Participant"
		 *
		 * @return The DomainParticipant "Participant"
		 */
		public synchronized static DDS.DomainParticipant getDomainParticipant() {
			return m_participant;
		}

		public final static class SubscriberWrapper {
			private static DDS.Subscriber m_subscriber = null;
			private static DDS.SubscriberListener m_subscriberListener = null;
			private static int m_statusMask = -1;

			private SubscriberWrapper() {
			}

			/**
			 * Create the DDS.Subscriber and start all child DataReaders.
			 * @throws WrapperException
			 */
			synchronized static void start() throws WrapperException {
				if (m_subscriber != null) {
					return;
				}

				DDS.SubscriberQosHolder subscriberQoSHolder = new DDS.SubscriberQosHolder();
				getSubscriberQoS(subscriberQoSHolder);

				if (m_subscriberListener == null) {
					m_subscriber = m_participant.create_subscriber(
							subscriberQoSHolder.value, m_subscriberListener,
							DDS.ANY_STATUS.value);
				} else {
					m_subscriber = m_participant.create_subscriber(
							subscriberQoSHolder.value, m_subscriberListener,
							m_statusMask);
				}

				subscriberQoSHolder = null;

				if (m_subscriber == null) {
					throw new WrapperException(null, m_participant,
							"DDS.DomainParticipant", "create_subscriber",
							DDS.RETCODE_OK.value,
							"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.start()");
				}

				track.BattleshipWrapper.addSubscriber(m_subscriber);

				setDefaultDataReaderQoS();

				try {
					PointTrackDataReaderWrapper.start();
				} catch (WrapperException eStart) {
					try {
						stop();
					} catch (WrapperException eStop) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();
						exceptions.add(eStart);
						exceptions.add(eStop);
						throw new ContainerWrapperException(exceptions);
					}

					throw eStart;
				}

				try {
					TrackStateDataReaderWrapper.start();
				} catch (WrapperException eStart) {
					try {
						stop();
					} catch (WrapperException eStop) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();
						exceptions.add(eStart);
						exceptions.add(eStop);
						throw new ContainerWrapperException(exceptions);
					}

					throw eStart;
				}

			}

			/**
			 * Stop all child DataReaders and delete the DDS.Subscriber.
			 * @throws WrapperException
			 */
			synchronized static void stop() throws WrapperException {
				if (m_subscriber == null) {
					return;
				}

				final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();
				track.BattleshipWrapper.removeSubscriber(m_subscriber);

				try {
					PointTrackDataReaderWrapper.stop();
				} catch (WrapperException e) {
					exceptions.add(e);
				}

				try {
					TrackStateDataReaderWrapper.stop();
				} catch (WrapperException e) {
					exceptions.add(e);
				}

				int retcode = m_participant.delete_subscriber(m_subscriber);
				m_subscriber = null;

				if (retcode != DDS.RETCODE_OK.value) {
					exceptions
							.add(new WrapperException(null, m_participant,
									"DDS.DomainParticipant",
									"delete_subscriber", retcode,
									"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.stop()"));
				}

				if (!exceptions.isEmpty()) {
					throw new ContainerWrapperException(exceptions);
				}
			}

			static void getSubscriberQoS(DDS.SubscriberQosHolder qos) {
				m_participant.get_default_subscriber_qos(qos);

				qos.value.presentation.access_scope = DDS.PresentationQosPolicyAccessScopeKind.INSTANCE_PRESENTATION_QOS;
				qos.value.presentation.coherent_access = false;
				qos.value.presentation.ordered_access = false;
				qos.value.entity_factory.autoenable_created_entities = true;

				qos.value.partition.name = new String[1];

				qos.value.partition.name[0] = track.BattleshipWrapper.getName();

				m_participant.set_default_subscriber_qos(qos.value);
			}

			private static void setDefaultDataReaderQoS() {
				DDS.DataReaderQosHolder qos = new DDS.DataReaderQosHolder();
				m_subscriber.get_default_datareader_qos(qos);

				qos.value.durability.kind = DDS.DurabilityQosPolicyKind.VOLATILE_DURABILITY_QOS;
				qos.value.deadline.period = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);
				qos.value.ownership.kind = DDS.OwnershipQosPolicyKind.SHARED_OWNERSHIP_QOS;

				qos.value.latency_budget.duration = new DDS.Duration_t(0, 0);
				qos.value.liveliness.kind = DDS.LivelinessQosPolicyKind.AUTOMATIC_LIVELINESS_QOS;
				qos.value.liveliness.lease_duration = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);

				// Not implemented in OpenSplice 3.2.2 and before
				qos.value.time_based_filter.minimum_separation = new DDS.Duration_t(
						0, 0);

				qos.value.reliability.kind = DDS.ReliabilityQosPolicyKind.BEST_EFFORT_RELIABILITY_QOS;
				qos.value.reliability.max_blocking_time = new DDS.Duration_t(0,
						100000000);
				qos.value.destination_order.kind = DDS.DestinationOrderQosPolicyKind.BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
				qos.value.history.kind = DDS.HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
				qos.value.history.depth = 1;
				qos.value.resource_limits.max_instances = -1;
				qos.value.resource_limits.max_samples = -1;
				qos.value.resource_limits.max_samples_per_instance = -1;
				qos.value.reader_data_lifecycle.autopurge_disposed_samples_delay = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);
				qos.value.reader_data_lifecycle.autopurge_nowriter_samples_delay = new DDS.Duration_t(
						DDS.DURATION_INFINITE_SEC.value,
						DDS.DURATION_INFINITE_NSEC.value);

				m_subscriber.set_default_datareader_qos(qos.value);
			}

			public synchronized static DDS.Subscriber getSubscriber() {
				return m_subscriber;
			}

			public final static class PointTrackDataReaderWrapper {
				private static track.PointTrackDataReader m_reader = null;
				private static DDS.DataReaderListener m_readerListener = null;
				private static int m_statusMask = -1;

				private PointTrackDataReaderWrapper() {
				}

				/**
				 * Create the "PointTrackDataReader".
				 * @throws WrapperException
				 */
				static synchronized void start() throws WrapperException {
					if (m_reader != null) {
						return;
					}

					DDS.TopicDescription topic = null;

					try {
						topic = track.PointTrack_topicWrapper
								.start(m_participant);
					} catch (track.PointTrack_topicWrapper.WrapperException e) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();

						exceptions.add(new WrapperException(e.getReason(), e
								.getEntity(), e.getSourceType(), e.getMethod(),
								e.getReturnValue(), e.getWrapper()));
						exceptions
								.add(new WrapperException(
										null,
										null,
										"PointTrack_topicWrapper",
										"start",
										DDS.RETCODE_OK.value,
										"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.PointTrackDataReaderWrapper.start()"));

						throw new ContainerWrapperException(exceptions);
					}

					DDS.DataReaderQosHolder dwQoS = new DDS.DataReaderQosHolder();
					getDataReaderQoS(dwQoS);

					/* Create datareader */

					DDS.DataReader dataReader = null;

					if (m_readerListener == null) {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener,
								DDS.ANY_STATUS.value);
					} else {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener, m_statusMask);
					}

					if (dataReader == null) {
						throw new WrapperException("Null returned",
								m_subscriber, "DDS.Subscriber", "create", 0,
								"PointTrackDataReaderWrapper.start()");
					}

					m_reader = track.PointTrackDataReaderHelper
							.narrow(dataReader);

					if (m_reader == null) {
						throw new WrapperException("Null returned", null,
								"track.PointTrackDataReaderHelper", "narrow",
								0, "PointTrackDataReaderWrapper.start()");
					}

				}

				/**
				 * Delete the "PointTrackDataReader".
				 * @throws WrapperException
				 */
				static synchronized void stop() throws WrapperException {
					if (m_reader == null) {
						return;
					}

					int retcode = m_subscriber.delete_datareader(m_reader);
					m_reader = null;

					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(null, m_subscriber,
								"DDS.Subscriber", "delete_datareader", retcode,
								"PointTrackDataReaderWrapper.stop()");
					}
				}

				/**
				 *
				 */
				static void getDataReaderQoS(DDS.DataReaderQosHolder qos) {
					m_subscriber.get_default_datareader_qos(qos);

					// Not implemented in OpenSplice 3.2.2 and before
					qos.value.time_based_filter.minimum_separation = new DDS.Duration_t(
							0, 0);

					qos.value.reader_data_lifecycle.autopurge_disposed_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.reader_data_lifecycle.autopurge_nowriter_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.durability.kind = DDS.DurabilityQosPolicyKind.VOLATILE_DURABILITY_QOS;
					qos.value.deadline.period = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);

					qos.value.latency_budget.duration = new DDS.Duration_t(0, 0);
					qos.value.liveliness.kind = DDS.LivelinessQosPolicyKind.AUTOMATIC_LIVELINESS_QOS;
					qos.value.liveliness.lease_duration = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.reliability.kind = DDS.ReliabilityQosPolicyKind.BEST_EFFORT_RELIABILITY_QOS;
					qos.value.reliability.max_blocking_time = new DDS.Duration_t(
							0, 100000000);
					qos.value.destination_order.kind = DDS.DestinationOrderQosPolicyKind.BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
					qos.value.history.kind = DDS.HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
					qos.value.history.depth = 1;
					qos.value.resource_limits.max_instances = -1;
					qos.value.resource_limits.max_samples = -1;
					qos.value.resource_limits.max_samples_per_instance = -1;
					qos.value.ownership.kind = DDS.OwnershipQosPolicyKind.EXCLUSIVE_OWNERSHIP_QOS;
				}

				/**
				 *
				 */
				public synchronized static track.PointTrackDataReader getDataReader() {
					return m_reader;
				}

				/**
				 * Attach a listener of type "PointTrackDataReaderListener" to this DataReader.
				 *
				 * @param listener The listener to attach
				 * @return A DDS return code for the "attach" operation
				 */
				public synchronized static void attach(
						PointTrackDataReaderListener listener)
						throws WrapperException {
					m_readerListener = listener;
					m_statusMask = listener.STATUS_MASK;
					DDS.DataReader reader = m_reader;

					if (reader == null) {
						return;
					}

					final int retcode = reader.set_listener(listener,
							listener.STATUS_MASK);
					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(
								null,
								reader,
								"DDS.DataReader",
								"set_listener",
								retcode,
								"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.PointTrackDataReaderWrapper.attach()");
					}
				}

				/**
				 * Detach the listener from this DataReader.
				 *
				 * @param listener The listener to detach
				 * @return A DDS return code for the "detach" operation
				 */
				public synchronized static void detach(
						PointTrackDataReaderListener listener)
						throws WrapperException {
					if (listener != m_readerListener) {
						throw new WrapperException(
								"Listener is not attached",
								null,
								"PointTrackDataReaderWrapper",
								"detach",
								DDS.RETCODE_OK.value,
								"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.PointTrackDataReaderWrapper.detach()");
					}

					m_readerListener = null;

					if (m_reader != null) {
						final int retcode = m_reader.set_listener(null, 0);
						if (retcode != DDS.RETCODE_OK.value) {
							throw new WrapperException(
									null,
									m_reader,
									"DDS.DataReader",
									"set_listener",
									retcode,
									"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.PointTrackDataReaderWrapper.detach()");
						}
					}

				}

			}

			public final static class TrackStateDataReaderWrapper {
				private static track.TrackStateDataReader m_reader = null;
				private static DDS.DataReaderListener m_readerListener = null;
				private static int m_statusMask = -1;

				private TrackStateDataReaderWrapper() {
				}

				/**
				 * Create the "TrackStateDataReader".
				 * @throws WrapperException
				 */
				static synchronized void start() throws WrapperException {
					if (m_reader != null) {
						return;
					}

					DDS.TopicDescription topic = null;

					try {
						topic = track.TrackState_topicWrapper
								.start(m_participant);
					} catch (track.TrackState_topicWrapper.WrapperException e) {
						final java.util.List<WrapperException> exceptions = new java.util.ArrayList<WrapperException>();

						exceptions.add(new WrapperException(e.getReason(), e
								.getEntity(), e.getSourceType(), e.getMethod(),
								e.getReturnValue(), e.getWrapper()));
						exceptions
								.add(new WrapperException(
										null,
										null,
										"TrackState_topicWrapper",
										"start",
										DDS.RETCODE_OK.value,
										"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.TrackStateDataReaderWrapper.start()"));

						throw new ContainerWrapperException(exceptions);
					}

					DDS.DataReaderQosHolder dwQoS = new DDS.DataReaderQosHolder();
					getDataReaderQoS(dwQoS);

					/* Create datareader */

					DDS.DataReader dataReader = null;

					if (m_readerListener == null) {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener,
								DDS.ANY_STATUS.value);
					} else {
						dataReader = m_subscriber.create_datareader(topic,
								dwQoS.value, m_readerListener, m_statusMask);
					}

					if (dataReader == null) {
						throw new WrapperException("Null returned",
								m_subscriber, "DDS.Subscriber", "create", 0,
								"TrackStateDataReaderWrapper.start()");
					}

					m_reader = track.TrackStateDataReaderHelper
							.narrow(dataReader);

					if (m_reader == null) {
						throw new WrapperException("Null returned", null,
								"track.TrackStateDataReaderHelper", "narrow",
								0, "TrackStateDataReaderWrapper.start()");
					}

				}

				/**
				 * Delete the "TrackStateDataReader".
				 * @throws WrapperException
				 */
				static synchronized void stop() throws WrapperException {
					if (m_reader == null) {
						return;
					}

					int retcode = m_subscriber.delete_datareader(m_reader);
					m_reader = null;

					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(null, m_subscriber,
								"DDS.Subscriber", "delete_datareader", retcode,
								"TrackStateDataReaderWrapper.stop()");
					}
				}

				/**
				 *
				 */
				static void getDataReaderQoS(DDS.DataReaderQosHolder qos) {
					m_subscriber.get_default_datareader_qos(qos);

					// Not implemented in OpenSplice 3.2.2 and before
					qos.value.time_based_filter.minimum_separation = new DDS.Duration_t(
							0, 0);

					qos.value.reader_data_lifecycle.autopurge_disposed_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.reader_data_lifecycle.autopurge_nowriter_samples_delay = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.deadline.period = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);

					qos.value.latency_budget.duration = new DDS.Duration_t(0, 0);
					qos.value.ownership.kind = DDS.OwnershipQosPolicyKind.SHARED_OWNERSHIP_QOS;
					qos.value.liveliness.kind = DDS.LivelinessQosPolicyKind.AUTOMATIC_LIVELINESS_QOS;
					qos.value.liveliness.lease_duration = new DDS.Duration_t(
							DDS.DURATION_INFINITE_SEC.value,
							DDS.DURATION_INFINITE_NSEC.value);
					qos.value.destination_order.kind = DDS.DestinationOrderQosPolicyKind.BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
					qos.value.history.kind = DDS.HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
					qos.value.history.depth = 1;
					qos.value.resource_limits.max_instances = -1;
					qos.value.resource_limits.max_samples = -1;
					qos.value.resource_limits.max_samples_per_instance = -1;
					qos.value.durability.kind = DDS.DurabilityQosPolicyKind.TRANSIENT_DURABILITY_QOS;
					qos.value.reliability.kind = DDS.ReliabilityQosPolicyKind.RELIABLE_RELIABILITY_QOS;
					qos.value.reliability.max_blocking_time = new DDS.Duration_t(
							0, 100000000);
				}

				/**
				 *
				 */
				public synchronized static track.TrackStateDataReader getDataReader() {
					return m_reader;
				}

				/**
				 * Attach a listener of type "TrackStateDataReaderListener" to this DataReader.
				 *
				 * @param listener The listener to attach
				 * @return A DDS return code for the "attach" operation
				 */
				public synchronized static void attach(
						TrackStateDataReaderListener listener)
						throws WrapperException {
					m_readerListener = listener;
					m_statusMask = listener.STATUS_MASK;
					DDS.DataReader reader = m_reader;

					if (reader == null) {
						return;
					}

					final int retcode = reader.set_listener(listener,
							listener.STATUS_MASK);
					if (retcode != DDS.RETCODE_OK.value) {
						throw new WrapperException(
								null,
								reader,
								"DDS.DataReader",
								"set_listener",
								retcode,
								"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.TrackStateDataReaderWrapper.attach()");
					}
				}

				/**
				 * Detach the listener from this DataReader.
				 *
				 * @param listener The listener to detach
				 * @return A DDS return code for the "detach" operation
				 */
				public synchronized static void detach(
						TrackStateDataReaderListener listener)
						throws WrapperException {
					if (listener != m_readerListener) {
						throw new WrapperException(
								"Listener is not attached",
								null,
								"TrackStateDataReaderWrapper",
								"detach",
								DDS.RETCODE_OK.value,
								"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.TrackStateDataReaderWrapper.detach()");
					}

					m_readerListener = null;

					if (m_reader != null) {
						final int retcode = m_reader.set_listener(null, 0);
						if (retcode != DDS.RETCODE_OK.value) {
							throw new WrapperException(
									null,
									m_reader,
									"DDS.DataReader",
									"set_listener",
									retcode,
									"Display.DisplayAppWrapper.ParticipantWrapper.SubscriberWrapper.TrackStateDataReaderWrapper.detach()");
						}
					}

				}

			}

		}

	}

}
